package com.business.core.wyc.dao.base;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.SQLQuery;

import com.business.core.wyc.util.bean.PageBean;
   
  
public abstract class AbstractDao<T, PK extends Serializable> extends WycHibernateDaoSupport implements CommonDao<T, PK>
{
	
	protected Log	logger	= LogFactory.getLog(AbstractDao.class);

	protected abstract Class<T> getClassType();
	

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ȡ��ʵ��ļ򵥶�����
	 * @see ��������:
	 * @return
	 */
	protected String getClassSimpleName()
	{
		return this.getClassType().getSimpleName();
	}

	public T save(T transientInstance)
	{
		this.getHibernateTemplate().saveOrUpdate(transientInstance);
		return transientInstance;
	}

	public T saveHasReturn(T transientInstance)
	{
		this.getHibernateTemplate().saveOrUpdate(transientInstance);
		return transientInstance;
	}

	public T merge(T persistentInstance)
	{
		getHibernateTemplate().merge(persistentInstance);
		return persistentInstance;
	}

	public void delete(T persistentInstance)
	{
		getHibernateTemplate().delete(persistentInstance);
	}

	public void deleteById(PK id)
	{
		this.delById(id);
	}

	public void delById(PK id)
	{
		T instance = findById(id);
		if (instance != null)
		{
			delete(instance);
		}
	}

	public void delByIds(PK[] ids)
	{
		if (ids == null || ids.length < 1)
			return;
		for (PK id : ids)
		{
			delById(id);
		}
	}

	public void delByPropert(String propertyName, Object value)
	{
		try
		{
			Query queryObject = getSession().createQuery("delete from " + getClassSimpleName() + " as model where model." + propertyName + "=?");
			queryObject.setParameter(0, value);
			queryObject.executeUpdate();
		}
		catch (RuntimeException re)
		{
			logger.error("delete by property name failed", re);
			throw re;
		}
	}

	protected int executeUpdate(String queryString)
	{
		return getHibernateTemplate().bulkUpdate(queryString);
	}

	protected int executeUpdate(String queryString, Object value)
	{
		return getHibernateTemplate().bulkUpdate(queryString, value);
	}

	protected int executeUpdate(String queryString, Object[] values)
	{
		return getHibernateTemplate().bulkUpdate(queryString, values);
	}

	public T findById(PK id)
	{
		try
		{
			T instance = (T) getHibernateTemplate().get(getClassType(), id);
			return instance;
		}
		catch (Exception e)
		{
			return null;
		}
	}

	public List<T> findAll()
	{
		return this.findAll(0, 0);
	}

	public List<T> findAll(int maxResults)
	{
		return this.findAll(0, maxResults);
	}

	public List<T> findAll(int offset, int maxResults)
	{
		String sql = "from " + getClassSimpleName();
		return this.findNotClobList(sql, null, offset, maxResults, true);
	}

	@SuppressWarnings("unchecked")
	public List<T> findBySql(String sql)
	{
		return getHibernateTemplate().find(sql);
	}

	public List<T> findBySql(String sql, int num)
	{
		return this.findByQueryString(sql, num);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ�����Ψһ�������ж�����¼���򷵻ص�һ��
	 * @see ��������:
	 * @param queryString
	 * @return
	 */
	protected T findUniqueResultByQueryString(String queryString)
	{
		return findUniqueResultByQueryStringValues(queryString, null);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ������Ψһ�������ж�����¼���򷵻ص�һ��
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected T findUniqueResultByQueryStringValues(String queryString, Object[] values)
	{
		Query queryObject = getSession().createQuery(queryString);
		if (values != null && values.length > 0)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		return (T) queryObject.uniqueResult();
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ����¼����
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected int findCountByQueryStringValues(String queryString)
	{
		return findCountByQueryStringValues(queryString, null);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ����¼����
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected int findCountByQueryStringValues(String queryString, Object[] values)
	{
		Query queryObject = getSession().createQuery(queryString);
		if (values != null && values.length > 0)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		return new Integer(queryObject.uniqueResult().toString());
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ������ȫ�����
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected List<T> findByQueryString(String queryString)
	{
		return findByQueryStringValues(queryString, null, 0, -1);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ������ȫ�����
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected List<T> findByQueryString(String queryString, int maxResults)
	{
		return findByQueryStringValues(queryString, null, 0, maxResults);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:���sql���͵�һ������������¼���ҽ��
	 * @see ��������:
	 * @param queryString
	 * @param firstResult
	 * @param maxResult
	 * @return
	 */
	protected List<T> findByQueryString(String queryString, int firstResult, int maxResult)
	{
		return findByQueryStringValues(queryString, null, firstResult, maxResult);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ������ȫ�����
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected List<T> findByQueryStringValues(String queryString, Object[] values)
	{
		return findByQueryStringValues(queryString, values, 0, -1);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݲ�ѯ�ַ������ֵ�����ط�ҳ���
	 * @see ��������:
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected List<T> findByQueryStringValues(String queryString, Object[] values, int offset, int maxResults)
	{
		Query queryObject = getSession().createQuery(queryString);
		if (values != null)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		return this.findNotClobList(queryString, values, offset, maxResults, false);
	}

	@SuppressWarnings("unchecked")
	protected List<T> findBySQLQueryStringValues(String queryString, Object[] values, int offset, int maxResults)
	{
		SQLQuery queryObject = getSession().createSQLQuery(queryString);
		if (values != null)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		if (maxResults > 0)
		{
			queryObject.setFirstResult(offset);
			queryObject.setMaxResults(maxResults);
		}
		queryObject.addEntity(this.getClassType());
		queryObject.setCacheable(true);
		return queryObject.list();
	}

	protected int findCountBySQLQueryStringValues(String queryString, Object[] values)
	{
		SQLQuery queryObject = getSession().createSQLQuery(queryString);
		if (values != null && values.length > 0)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		queryObject.addEntity(this.getClassType());
		queryObject.setCacheable(true);
		return new Integer(queryObject.list().size());
	}


	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������:��ݶ������Ժ�ֵ���ж����ѯ
	 * @see ��������:
	 * @param propertyName
	 * @param value
	 * @param maxResults С�ڵ���0ʱ��ʾ��ѯ��ȡȫ�����
	 * @return
	 */
	public List<T> findByProperty(String propertyName, Object value, int maxResults)
	{
		String sql = "from " + getClassSimpleName() + " as model where model." + propertyName + "=?";
		Object[] values = { value };
		return this.findByQueryStringValues(sql, values, 0, maxResults);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������: ��ҳ����
	 * @see ��������:
	 * @param pageBean
	 * @param strSqlCount �����ܼ�¼���sql��䣬��ֵ
	 * @param strSqlList ���Ҽ�¼��sql��䣬��ֵ
	 * @return
	 */
	public PageBean findPageList(PageBean pageBean, String strSqlCount, String strSqlList)
	{
		return this.findPageList(pageBean, strSqlCount, strSqlList, null);
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������: ��ҳ����
	 * @see ��������:
	 * @param pageBean
	 * @param strSqlCount �����ܼ�¼���sql��䣬����ֵ, ֵ�ķ�ʽ { 1,2 }
	 * @param strSqlList ���Ҽ�¼��sql��䣬����ֵ,ֵ�ķ�ʽ { 1,2 }
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public PageBean findPageList(PageBean pageBean, String strSqlCount, String strSqlList, Object[] values)
	{
		if (null == pageBean || null == strSqlCount || "".equals(strSqlCount.trim()) || null == strSqlList || "".equals(strSqlList.trim()))
			return null;
		// �ܼ�¼����
		int totalRows = this.findCountByQueryStringValues(strSqlCount, values);
		pageBean.setTotalRows(totalRows);
		List resultSetList = this.findByQueryStringValues(strSqlList, values, pageBean.getOffset(), pageBean.getRowsPerPage());
		// ����ҳ��Ϣ����PageBean����// ����¼���ϼ���ҳ��Ϣ,����request��
		pageBean.setResultSetList(resultSetList);
		return pageBean;
	}

	/**
	 * @date Sep 9, 2009
	 * @author yuyz
	 * @see ��������: ��ҳ���� [����SQL����ѯ] ��:select * from TblGroup where id in (select targetId from TblForum)
	 * @see ��������:
	 * @param pageBean
	 * @param strSqlCount
	 * @param strSqlList
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public PageBean findBySQLPageList(PageBean pageBean, String strSqlCount, String strSqlList, Object[] values)
	{
		if (null == pageBean || null == strSqlCount || "".equals(strSqlCount.trim()) || null == strSqlList || "".equals(strSqlList.trim()))
			return null;
		// �ܼ�¼����
		int totalRows = this.findCountBySQLQueryStringValues(strSqlCount, values);
		pageBean.setTotalRows(totalRows);
		List resultSetList = this.findBySQLQueryStringValues(strSqlList, values, pageBean.getOffset(), pageBean.getRowsPerPage());
		// ����ҳ��Ϣ����PageBean����// ����¼���ϼ���ҳ��Ϣ,����request��
		pageBean.setResultSetList(resultSetList);
		return pageBean;
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������: ���Ұ�clob�ֶε�list
	 * @see ��������:
	 * @param sql sql���
	 * @param values ����
	 * @param offset ��һ����¼
	 * @param maxResults ���һ����¼
	 * @param setCacheable �Ƿ����û���
	 * @return
	 */
	@SuppressWarnings({ "unused", "unchecked" })
	private List<T> findClobList(String sql, Object[] values, int offset, int maxResults, boolean setCacheable)
	{
		Query queryObject = getSession().createQuery(sql);
		if (values != null)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		if (offset > 0)
			queryObject.setFirstResult(offset);
		if (maxResults > 0)
			queryObject.setMaxResults(maxResults);
		if (setCacheable)
			queryObject.setCacheable(setCacheable);
		List list = null;
		try
		{
			list = queryObject.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
		if (null == list || list.isEmpty() || list.size() == 0)
			return null;
		else
		{
			List<T> newList = new ArrayList<T>();
			for (Object o : list)
				newList.add(this.findById((PK) o));
			return newList;
		}
	}

	/**
	 * @date 2013-5-14
	 * @author wyc
	 * @see ��������: ���Ҳ���clob�ֶε�list
	 * @see ��������:
	 * @param sql sql���
	 * @param values ����
	 * @param offset ��һ����¼
	 * @param maxResults ���һ����¼
	 * @param setCacheable �Ƿ����û���
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<T> findNotClobList(String sql, Object[] values, int offset, int maxResults, boolean setCacheable)
	{
		Query queryObject = getSession().createQuery(sql);
		if (values != null)
		{
			for (int i = 0; i < values.length; i++)
			{
				queryObject.setParameter(i, values[i]);
			}
		}
		if (offset > 0)
			queryObject.setFirstResult(offset);
		if (maxResults > 0)
			queryObject.setMaxResults(maxResults);
		if (setCacheable)
			queryObject.setCacheable(setCacheable);
		try
		{
			return queryObject.list();
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
}
